// Copyright (c) 2020 Presto Labs Pte. Ltd.
// Author: taekwon, xguo

#pragma once

#include <cstdio>
#include <memory>
#include <string>
#include <unordered_map>
#include <unordered_set>

#include <rapidjson/document.h>

#include "coin2/exchange/base/order/order.h"
#include "coin2/exchange/huobi/symbology/currency.h"
#include "coin2/exchange/huobi_futures/symbology/product.h"

namespace coin2::exchange::huobi_futures::order_v1 {

class HuobiFuturesParser : public base::order::BaseParser {
 public:
  HuobiFuturesParser() : is_prepared_(false) {}
  const ParseResult& ParseRawMessage(const RawMessage& msg) override;
  AccountBalance ParseBalance(const JsonValue& doc) override;
  AccountPosition ParsePosition(const JsonValue& doc) override;
  CurrencyTransferBundle ParseTransfer(const JsonValue& doc);
  bool ParseRawBalance(const JsonValue& doc, RawBalanceMap* raw_balance_map);
  bool ParseRawPosition(const JsonValue& doc, RawPositionMap* raw_position_map);
  bool ParseRawBalanceWithCrossMode(const JsonValue& doc, RawBalanceMap* raw_balance_map);
  bool ParseRawBalanceWithLinearMode(const JsonValue& doc, RawBalanceMap* raw_balance_map);
  bool ParseRawBalanceWithNormalMode(const JsonValue& doc, RawBalanceMap* raw_balance_map);

 private:
  void ParseSubmitResponse();
  void ParseBatchSubmitResponse();
  void ParseCancelResponse();
  void ParseRestOpenOrdersInfo();
  void ParseRestCancelOrdersInfo();
  void ParseRestFillInfoList();
  void ParseRestAccountBalance();
  void ParseRestAccountPosition();
  void ParseRestTransfer();
  void ParseWsMessage();

  void ParseRestAccountCrossBalance();
  void ParseRestAccountNonCrossBalance();
  void ParseRestAccountCrossPosition();
  void ParseRestAccountNonCrossPosition();
  void ParseRestCrossAndNonCrossPosition();

  ProductOrderBundle ParseWsOrderInfoListV2(const JsonValue& data);
  ProductFillBundle ParseWsFillInfoListV2(const JsonValue& data);
  coin::proto::ProductOrderElement ParseOrderInfo(
      const JsonValue& data,
      const std::string& version = "v1");
  AccountBalance ParseCrossBalance(const JsonValue& doc);
  AccountBalance ParseNormalBalance(const JsonValue& doc);
  AccountBalance ParseLinearBalance(const JsonValue& doc);
  AccountBalance ParseCrossBalanceFromWs(const JsonValue& doc);
  AccountBalance ParseNormalBalanceFromWs(const JsonValue& doc);
  AccountBalance ParseLinearBalanceFromWs(const JsonValue& doc);
  void Prepare();

 private:
  std::unordered_set<std::string> usdt_ccys_;
  RawBalanceMap usdt_cache_map_;
  bool ignore_balance_event_ = false;
  bool is_prepared_ = false;
  bool is_account_balance_initialized_ = false;
  bool is_account_position_initialized_ = false;

  // for readonly og
  // balance
  RawBalanceMap cross_balance_map_cache_;
  RawBalanceMap non_cross_balance_map_cache_;
  bool is_non_cross_balance_initialized_ = false;
  bool is_cross_balance_initialized_ = false;
  // position
  RawPositionMap cross_position_map_cache_;
  RawPositionMap non_cross_position_map_cache_;
  bool is_non_cross_position_initialized_ = false;
  bool is_cross_position_initialized_ = false;
};

}  // namespace coin2::exchange::huobi_futures::order_v1
